package com.bolt.report.engine.export.excel;

import com.bolt.report.engine.FillElement;
import com.bolt.report.engine.fill.FillChartElement;
import com.bolt.report.engine.fill.FillImageElement;
import com.bolt.report.engine.model.*;
import com.bolt.report.exception.ReportException;
import com.bolt.report.util.StyleUtil;
import com.bolt.report.util.ToolUtil;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class ExcelExporter extends BaseExcelExporter {

    int rowNumber = 0;

    public ExcelExporter() {
        super();
    }

    public ExcelExporter(Map<String, Object> parameters) {
        super(parameters);
    }

    @Override
    public void exportReport() throws ReportException {
        initInput();
        outputStream = getExporterOutput().getOutputStream();
        try {
            exportReportTStream();
        } catch (Exception ex) {
            throw new ReportException(ex);
        } finally {
            workbook.dispose();
            getExporterOutput().close();
        }
    }

    protected void exportReportTStream() throws ReportException, IOException {
        workbook = new SXSSFWorkbook(100000);
        exportPage();
        workbook.write(outputStream);
    }


    protected void exportColumnHeader(ColumnHeader columnHeader) throws IOException {
        exportBand(columnHeader);
    }

    protected void exportPage() throws IOException {
        List<PageDetails> pages = reportPrint.getPages();
        ColumnHeader columnHeader = reportPrint.getColumnHeader();
        Title title = reportPrint.getTitle();
        if (pages != null && pages.size() > 0) {
            PageRange pageRange = getPageRange();
            int startPageIndex = pageRange.getStartPageIndex();
            int endPageIndex = pageRange.getEndPageIndex();
            PageDetails page = null;
            for (; startPageIndex <= endPageIndex; startPageIndex++) {
                page = pages.get(startPageIndex);
                if (reportPrint.isIgnorePagination()) {
                    sheet = createSheet(workbook, reportPrint, null);
                } else {
                    sheet = createSheet(workbook, reportPrint, "第" + (startPageIndex + 1) + "页");
                    rowNumber = 0;
                }
                if (title != null && title.isLoopPrintTitle(startPageIndex)) {
                    exportBand(title);
                }
                if (columnHeader != null && columnHeader.isLoopPrintHead(startPageIndex)) {
                    exportBand(columnHeader);
                }
                if (page != null) {
                    exportBand(page);
                }

            }
        }
    }

    protected void exportBand(BaseBand baseBand) throws IOException {
        Table table = baseBand.getTable();
        List<Column> columns = table.getColumns();
        List<Row> rows = table.getRows();
        if (columns.isEmpty() || rows.isEmpty()) {
            return;
        }
        for (int r = 0; r < rows.size(); r++) {
            Row row = rows.get(r);
            if (row.isEmpty()) {
                continue;
            }
            org.apache.poi.ss.usermodel.Row xlsRow = sheet.getRow(rowNumber);
            if (xlsRow == null) {
                xlsRow = sheet.createRow(rowNumber);
                xlsRow.setHeightInPoints(ToolUtil.pixelToPoint(row.getHeight()));
            }
            int skipCol = 0;
            for (int c = 0; c < columns.size(); c++) {
                Column col = columns.get(c);
                if (col.isHide()) {
                    skipCol++;
                    continue;
                }
                Cell cell = row.getCell(col);
                if (cell == null) {
                    continue;
                }
                int colNum = c - skipCol;
                org.apache.poi.ss.usermodel.Cell xlsCell = xlsRow.getCell(colNum);
                if (xlsCell == null) {
                    xlsCell = xlsRow.createCell(colNum);
                }
                XSSFCellStyle xssfCellStyle = StyleUtil.transformXlsStyle(workbook, cell.getStyle());
                if (col.getWidth() > 0) {
                    float colWidth = ToolUtil.pixelToPoiWidth(col.getWidth());
                    sheet.setColumnWidth(colNum, (short) colWidth);
                }
                xlsCell.setCellStyle(xssfCellStyle);


                if (cell.getColSpan() > 0 || cell.getRowSpan() > 0) {
                    int colSpan = cell.getColSpan(), rowSpan = cell.getRowSpan();

                    if (rowSpan > 0) {
                        createBlankRow(rowNumber + 1, rowNumber + rowSpan, columns.size() - skipCol);
                        rowSpan--;

                    }
                    if (colSpan > 0) {
                        colSpan--;
                    }
                    if (colSpan > 0 || rowSpan > 0) {
                        CellRangeAddress cellRegion = new CellRangeAddress(rowNumber, (rowNumber + rowSpan), c - skipCol, (c - skipCol + colSpan));
                        sheet.addMergedRegion(cellRegion);
                    }

                }
                FillElement element = cell.getElement();
                if (element instanceof FillChartElement) {

                } else if (element instanceof FillImageElement) {
                    buildImage(cell);
                } else {
                    xlsCell.setCellValue((String) cell.getElement().getValue());
                }


            }
            row.setHeight((short) ToolUtil.pointToTwip(row.getHeight()));

            rowNumber++;
        }
    }

    private void createBlankRow(int startRow, int rowSize, int cellSize) {
        for (int i = startRow; i < rowSize; i++) {
            org.apache.poi.ss.usermodel.Row xlsRow = sheet.createRow(i);
            for (int c = 0; i < cellSize; i++) {
                xlsRow.createCell(c);
            }
        }
    }

}